149. Max Points on a Line(Linkedin Hard)(Java)

作者:JY

题目:Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

分析:题目给出二维点,我们需要求最大的共线点的个数,看到题目我们需要思考如何判断最多的共线点,点(x1, y1),(x2, y2),(x3, y3)三点共线条件是:(y2-y1)/(x2-x1) = (y3-y1)/(x3-x1),对于每个点p出发,对与该点到所有点的斜率我们需要计算出来,判断相同数值的总和其中最多的个数加1(出发点p)即为最多的共线点。但是还有两点特殊情况需要考虑,当x1 = x2,y1!=y2时,为垂直连线,计算斜率时分母为0会出错。
当x1 = x2,y1 = y2时,两点重合,则(x2, y2)和所有(x1, y1)的连线共线。

题解1:Brute Force
n个点总共构成n*(n-1)/2条直线,然后对每条直线看看是有多少点在直线上,记录最大值,最后返回结果。而判断一个点i在j,k构成的直线上的条件是points[k].y-points[i].y)(points[j].x-points[i].x)==(points[j].y-points[i].y)(points[k].x-points[i].x)。算法总共是三层循环.
Time complexity: O(n^3)
Space complexity: O(1)
代码如下:

  public class Solution {
    public int maxPoints(Point[] points) {
        int result = 0, n = points.length;
        for (int i = 0; i < n; ++i) {
            int inSame = 1;
            for (int j = i + 1; j < n; ++j) {
                int newResult = 0;
                long a.x = points[i].x, a.y = points[i].y;
                long b.x = points[j].x, b.y = points[j].y;
                if (a.x == b.x && a.y == b.y) {
                    ++inSame;
                    continue;
                }for (int k = 0; k < n; ++k) {
                    int c.x = points[k].x, c.y = points[k].y;
                    if (a.x*b.y + b.x*c.y + c.x*a.y - c.x*b.y - b.x*a.y - a.x * c.y == 0) {
                        ++newresultult;
                    }
                }
                result = Math.max(result, newResult);
            }
            result = Math.max(result, inSame);
        }
        return result;
    }
}

题解2:HashMap空间换时间
哈希表来记录斜率和共线点个数之间的映射,对每个点建立map,斜率是key。 计算斜率分数时,用gcd法。我们还需要顶一个变量duplicate来记录重合点的个数,与哈希表中数值相加,共线点个数总和。
Time complexity: O(n^2)
Space complexity: O(n)
代码如下:

  public class Solution{
        public int maxPoints(Point[] points) {
            if (points==null) return 0;
            if (points.length<=2) return points.length;
            int res=0;
            for (int i=0;i<points.length;i++){ 
                Map<String,Integer> map = new HashMap<>();
           //HashMap第一遍遍历所有点,第二遍还是遍历所有点,只要两个点不是同一个点,我们就求出这两两个点的斜率
             //key用来存斜率,value用来存当前斜率下点的个数
                int inSame=0;//定义两个变量用来表示两点重合的情况和在x轴上的情况
                int xAxis =0;
                 int l = points.length;
            for (int j = i + 1; j < l; j++) {
                int x = points[i].x - points[j].x;//分子
                int y = points[i].y - points[j].y;//分母
                if (x == 0 && y == 0) {
                    inSame++;
                    continue;
                }
                int gcd = helper(x, y);
                x /= gcd;
                y /= gcd;
                // 用string来存储斜率
                String slope = String.valueOf(x) + String.valueOf(y);
                int count = map.getOrDefault(slope, 0);
                count++;
                map.put(slope, count);
                xAxis = Math.max(xAxis, count);
            }
            res = Math.max(res, xAxis + inSame + 1);
        }
        return res;
    }
    public int helper(int x, int y) {//最大公约数函数,辗转相除法
        if (y == 0) return x;
        return helper(y, x % y);
    }
  }